let res = 99;
let expected = 0;

for (let i = 0; i < 12; i++) {
    res -= 1.5 * i;
}

if (res != expected)
    throw "res = " + res + ", expected = " + expected;

res = 0;
expected = 4995;

for (let i = 10; i > -101; i--) {
    res -= i;
}

if (res != expected)
    throw "res = " + res + ", expected = " + expected;

res = 1;
expected = 131.6818944;

for (let i = 1; i < 10; i++) {
    res *= 0.5 * i;
    res *= 0.2 * i;
}

if (res - expected > 0.00001 || expected - res > 0.00001)
    throw "res = " + res + ", expected = " + expected;

res = 131681894400;
expected = 1;

for (let i = 1; i < 10; i++) {
    res /= i / 0.2;
    res /= i / 0.5;
    res *= 10;
}

if (res - expected > 0.00001 || expected - res > 0.00001)
    throw "res = " + res + ", expected = " + expected;


res = 99;
expected = 0;

for (let i = 0; i < 12; i++) {
        res += - 1.5 * i;
    }

if (res != expected)
    throw "res = " + res + ", expected = " + expected;


res = -2147483640;
expected = -2147483740;

res = res - 100;

if (res != expected)
    throw "res = " + res + ", expected = " + expected;

res = 111111111 * 111111111;
expected = 12345678987654321;

if (res != expected)
    throw "res = " + res + ", expected = " + expected

res = 0;
res = 1 / -res;
expected = -Infinity;

if (res != expected)
    throw "res = " + res + ", expected = " + expected

res = -2147483648;
res = -res;
expected = 2147483648;

if (res != expected)
    throw "res = " + res + ", expected = " + expected

res = 0;
res = -res;
expected = 0;

if (res != expected)
    throw "res = " + res + ", expected = " + expected

res = -2147483648;
res = -res;
expected = 2147483648;

if (res != expected)
    throw "res = " + res + ", expected = " + expected

function verify(res, expected, msg) {
    if (res == expected) return;
    let err = "FAIL: " + msg + ":\n\texpected: " + expected + "\n\tgot     : " + res;
    throw err;
}

// shl2dyn, shr2dyn
function test_shifts() {
    verify(3 << 2, 12, "shl i32");
    verify((-3) << 2, -12, "shl i32 neg");
    verify(1.6 << 2, 4, "shl f64");
    verify((-1.6) << 2, -4, "shl f64 neg");
    verify(NaN << 2, 0, "shl nan 1");
    verify(6 << NaN, 6, "shl nan 2");
    verify(((1 / 0) / (1 / 0)) << 1, 0, "shl qnan");
    verify(Infinity << 2, 0, "shl inf 1");
    verify(7 << Infinity, 7, "shl inf 2");
    verify(1000000000 << 3, -589934592, "shl i32 ovf");
    verify(10000000000 << 3, -1604378624, "shl f64 ovf");
    verify(12 >> 2, 3, "shr i32");
    verify((-12) >> 2, -3, "shr i32 neg");
    verify(16.6 >> 2, 4, "shr f64");
    verify((-16.6) >> 2, -4, "shr f64 neg");
    verify(NaN >> 2, 0, "shr nan 1");
    verify(6 >> NaN, 6, "shr nan 2");
    verify(((1 / 0) / (1 / 0)) >> 1, 0, "shr qnan");
    verify(Infinity >> 2, 0, "shr inf 1");
    verify(7 >> Infinity, 7, "shr inf 2");
    verify(2147483648 >> 1, -1073741824, "shr left i32 ovf");
    verify(10000000000 >> 3, 176258176, "shr left f64 ovf");
}
test_shifts();

// negate
function test_negate() {
    verify(!0, true, "negate i32 0");
    verify(!1, false, "negate i32 1");
    verify(!false, true, "negate i32 false");
    verify(!true, false, "negate i32 true");
    verify(!10, false, "negate i32 10");
    verify(!0.1, false, "negate f64 0.1");
    verify(!0.0000000000000001, false, "negate f64 0.1");
    verify(!NaN, true, "negate NaN");
    verify(!undefined, true, "negate undefined");
    verify(!(2147483648), false, "negate i32 ovf");
    verify(!"", true, "negate String with length=0");
    verify(!"f", false, "negate String with length!=0");
    verify(!Infinity, false, "negate Infinity");
}
test_negate();

// ldlexenvdyn, ldlexvardyn
function capt(x1) {
    return function(x2) {
        return function() { return x1 + x2; };
    }
}
res = capt(1)(2)();
expected = 3;

if (res != expected) {
    throw "res = " + res + ", expected = " + expected;
}

// add2dyn
function test_add() {
    verify(1 + 2, 3, "add i32");
    verify(-12345678 + 23456789, 11111111, "add i32 sgne");
    verify(2147483647 + 1, 2147483648, "add i32 ovf");
    verify(3.14 + 3.14, 6.28, "add fp");
    verify("aaa" + "bbb", "aaabbb", "add str");
    verify(Infinity + 1, Infinity, "add Infinity left");
    verify(1 + (-Infinity), -Infinity, "add -Infinity right");
}
test_add();

// sub2dyn
function test_sub() {
    verify(1 - 2, -1, "sub i32");
    verify(12345678 - 23456789, -11111111, "sub i32 sgne");
    verify((-(2147483647)) - 2, -2147483649, "sub i32 ovf");
    verify(Infinity - 1, Infinity, "sub Infinity left");
    verify(1 - Infinity, -Infinity, "sub Infinity right");
}
test_sub();

function test_1() {
    verify(0xffffffff & ~1, -2, "And: double, smi");
    verify(~1 & 0xffffffff, -2, "And: smi, double");
    verify(0xffffffff & 0xaaaaaaaa, -1431655766, "And: double, double");
    verify(0xffffffff0 & ~1, -16, "");

    verify(-1 | 2, -1, "Or: negative smi, smi");
    verify(-1 | -2, -1, "Or: negative smi, negative smi");
    verify(0xffffffff | ~1, -1, "Or: double, smi");
    verify(~1 | 0xffffffff, -1, "Or: smi, double");
    verify(0xffffffff | 0xaaaaaaaa, -1, "Or: double, double");

    verify(-1 ^ 2, -3, "Xor: negative smi, smi");
    verify(-1 ^ -2, 1, "Xor: negative smi, negative smi");
    verify(0xffffffff ^ ~1, 1, "Xor: double, smi");
    verify(~1 ^ 0xffffffff, 1, "Xor: smi, double");
    verify(0xffffffff ^ 0xaaaaaaaa, 1431655765, "Xor: double, double");
}
test_1();

//exception handling
function foo1() {
    let capt1 = "capt1";
    try {
        let capt2 = "capt2";
        let fn = function() { return capt1 + capt2; };
        fn();
        function foo2() {
            throw fn;
        }
        foo2();
    } catch(e) {
        return String("foo1 caught " + e());
    }
}
res = foo1();
expected = "foo1 caught capt1capt2"

if (res != expected) {
    throw "res = " + res + ", expected = " + expected;
}